﻿// ———————————————————————–
// <copyright file="ClientType.cs" company="The MITRE Corporation">
//    Copyright (c) 2012 The MITRE Corporation. All rights reserved.
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// </copyright>
// ———————————————————————–
/////////////////////////////////////////////////////////////////////////////////////////////////
// ClientType.cs - Library Class for the TEP Message
// Project: IC.NET - TEP Library
//
// Language:    C#, .NET 4.0
// Platform:    Windows 7, VS 2010 Beta 2
// Author:      Lizzie DeYoung MITRE
//              Brian Wilkins  MITRE

/////////////////////////////////////////////////////////////////////////////////////////////////

// Copyright (c) 2012 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-12-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)using System;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using EDXLSharp.EDXLCTLib;

namespace EDXLSharp.EDXLTEPLib
{
  public class ClientType : ITEPComposableObject
  {
    #region internal classes
    public class ClientIDType : ITEPComposableObject
    {

      #region Private Member Variables

      private string id;
      private string source;

      #endregion //Private Memeber Variables

      #region Constructors
      #endregion // Constructors

      #region Public Accessors

      public string ID
      {
        get { return this.id; }
        set { this.id = value; }
      }

      public string Source
      {
        get { return this.source; }
        set { this.source = value; }
      }

      #endregion // Public Accessors

      #region Public Member Functions

      public override void WriteXML(XmlWriter xwriter, string name)
      {
        this.Validate();

        xwriter.WriteStartDocument(false);
        xwriter.WriteStartElement(name);

        xwriter.WriteElementString("ID", this.id);
        xwriter.WriteElementString("source", this.source);

        xwriter.WriteEndElement();
      }

      public override void ReadXML(XmlNode rootnode)
      {
        XmlNode clientidroot = rootnode;

        foreach (XmlNode node in clientidroot)
        {
          if (String.IsNullOrEmpty(node.InnerText))
          {
            continue;
          }

          switch (node.LocalName)
          {
            case "ID":
              this.id = node.InnerText;
              break;
            case "source":
              this.source = node.InnerText;
              break;
          }
        }

        this.Validate();
      }

      #endregion // Public Member Functions

      #region Private Member Functions

      protected override void Validate()
      {
        if (String.IsNullOrEmpty(this.id))
        {
          throw new ArgumentException("ID is a required field and cannot be null.");
        }
        if (String.IsNullOrEmpty(this.source))
        {
          throw new ArgumentException("Source is a required field and cannot be null.");
        }
      }

      #endregion // Private Member Functions
    }

    public class ClientAgeType : ITEPComposableObject
    {

      #region Private Member Variables

      private uint age;
      private EstimateTypeWrapper estimated;
      private ValueKeyType units;
      private AgeUnitsDefaultType unitsDefault;
      
      #endregion //Private Member Variables

      #region Constructors

      public ClientAgeType()
      {
      }

      #endregion // Constructors

      #region Public Accessors
      
    public uint Age
    {
      get { return this.age; }
      set { this.age = value; }
    }
      
    public EstimateTypeWrapper Estimated
    {
      get { return this.estimated; }
      set { this.estimated = value; }
    }
      
    public ValueKeyType Units
    {
      get { return this.units; }
      set { this.units = value; }
    }
      
    public AgeUnitsDefaultType UnitsDefault
    {
      get { return this.unitsDefault; }
      set { this.unitsDefault = value; }
    }

      #endregion // Public Accessors

      #region Public Member Functions

      public override void WriteXML(XmlWriter xwriter, string name)
      {
        this.Validate();

        xwriter.WriteStartDocument(false);
        xwriter.WriteStartElement(name);

        xwriter.WriteElementString("age", this.age.ToString());
        this.estimated.WriteXML(xwriter, "estimated");
        if (this.units != null)
        {
          this.units.WriteXML(xwriter, "units");
        }
        else
        {
          this.unitsDefault.WriteXML(xwriter, "unitsDefault");
        }

        xwriter.WriteEndElement();
      }

      public override void ReadXML(XmlNode rootnode)
      {
        foreach (XmlNode node in rootnode)
        {
          if (String.IsNullOrEmpty(node.InnerText))
          {
            continue;
          }

          switch (node.LocalName)
          {
            case "age":
              this.age = uint.Parse(node.InnerText);
              break;
            case "estimated":
              if(this.estimated == null)
              {
                this.estimated = new EstimateTypeWrapper();
              }
              this.estimated.ReadXML(node);
              break;
            case "units":
              if(this.units == null)
              {
                this.units = new ValueKeyType();
              }
              this.units.ReadXML(node);
              break;
            case "unitsDefault":
              if(this.unitsDefault == null)
              {
                this.unitsDefault = new AgeUnitsDefaultType();
              }
              this.unitsDefault.ReadXML(node);
              break;
          }
        }

        this.Validate();
      }

      #endregion // Public Member Functions

      #region Private Member Functions

      protected override void Validate()
      {
        if (this.estimated == null)
        {
          throw new ArgumentNullException("A estimated element is required. No null values.");
        }
        if (this.units != null && this.unitsDefault != null)
        {
          throw new ArgumentException("Only one of units or unitsDefault can be used, not both.");
        }
        if (this.units == null && this.unitsDefault == null)
        {
          throw new ArgumentNullException("One of units or unitsDefault must be defined.");
        }
      }

      #endregion // Private Member Functions
    }

    #endregion // internal classes

    
    #region Private Member Variables
    private List<ClientIDType> clientId;
    private GenderDefaultType gender;
    private ClientAgeType clientAge;
    private List<ValueListType> raceEthnicity;
    // todo: date of birth
    private PersonDetailsType personalId;
    private ValueKeyType hairColor;
    private ValueKeyType eyeColor;
    private EDXLStringTypeWrapper distinguishingMarks;
    private ValueKeyType primarySpokenLanguage;
    private List<ValueListType> specialTransportationNeeds;
    private List<ValueListType> specialMedicalNeeds;
    private List<ValueListType> medicationAllergies;
    private List<MedicationType> currentMedication;
    private EDXLStringTypeWrapper familyUnificationCode;
    private ValueListType barriersToPatientCare;
    private ValueKeyType evacuationDestinationRequired;
    private ClientEvacuationStatusDefaultType evacuationDestinationRequiredDefault;
    private PersonDetailsType clientContactInformation;
    private List<PersonDetailsType> closestRelativeGuardianContactInformation;
    private ValueListType specialClassification;
    private ClientEvacuationStatusDefaultType specialClassificationDefault;
    private SituationType situation;
    private HealthCareProviderType healthCareProvider;
    private ClientEncounterType clientEncounter;

    #endregion //Private Member Variables

    #region Constructors
    
    public ClientType()
    {
      // initialize all lists
      raceEthnicity = new List<ValueListType>();
      specialTransportationNeeds = new List<ValueListType>();
      specialMedicalNeeds = new List<ValueListType>();
      medicationAllergies = new List<ValueListType>();
      currentMedication = new List<MedicationType>();
      closestRelativeGuardianContactInformation = new List<PersonDetailsType>();
    }
    
    #endregion // Constructors

    #region Public Accessors

    
    public List<ClientIDType> ClientID
    {
      get { return this.clientId; }
      set { this.clientId = value; }
    }
    
    public GenderDefaultType Gender
    {
      get { return this.gender; }
      set { this.gender = value; }
    }

    public ClientAgeType ClientAge
    {
      get { return this.clientAge; }
      set { this.clientAge = value; }
    }

    public List<ValueListType> RaceEthnicity
    {
      get { return this.raceEthnicity; }
      set { this.raceEthnicity = value; }
    }

    public PersonDetailsType PersonalID
    {
      get { return this.personalId; }
      set { this.personalId = value; }
    }

    public ValueKeyType HairColor
    {
      get { return this.hairColor; }
      set { this.hairColor = value; }
    }

    public ValueKeyType EyeColor
    {
      get { return this.eyeColor; }
      set { this.eyeColor = value; }
    }

    public EDXLStringTypeWrapper DistinguishingMarks
    {
      get { return this.distinguishingMarks; }
      set { this.distinguishingMarks = value; }
    }

    public ValueKeyType PrimarySpokenLanguage
    {
      get { return this.primarySpokenLanguage; }
      set { this.primarySpokenLanguage = value; }
    }

    public List<ValueListType> SpecialTransportationNeeds
    {
      get { return this.specialTransportationNeeds; }
      set { this.specialTransportationNeeds = value; }
    }

    public List<ValueListType> SpecialMedicalNeeds
    {
      get { return this.specialMedicalNeeds; }
      set { this.specialMedicalNeeds = value; }
    }

    public List<ValueListType> MedicationAllergies
    {
      get { return this.medicationAllergies; }
      set { this.medicationAllergies = value; }
    }

    public List<MedicationType> CurrentMedication
    {
      get { return this.currentMedication; }
      set { this.currentMedication = value; }
    }

    public EDXLStringTypeWrapper FamilyUnificationCode
    {
      get { return this.familyUnificationCode; }
      set { this.familyUnificationCode = value; }
    }

    public ValueListType BarriersToPatientCare
    {
      get { return this.barriersToPatientCare; }
      set { this.barriersToPatientCare = value; }
    }

    public ValueKeyType EvacuationDestinationRequired
    {
      get { return this.evacuationDestinationRequired; }
      set { this.evacuationDestinationRequired = value; }
    }

    public ClientEvacuationStatusDefaultType EvacuationDestinationRequiredDefault
    {
      get { return this.evacuationDestinationRequiredDefault; }
      set { this.evacuationDestinationRequiredDefault = value; }
    }

    public PersonDetailsType ClientContactInformation
    {
      get { return this.clientContactInformation; }
      set { this.clientContactInformation = value; }
    }

    public List<PersonDetailsType> ClosestRelativeGaurdianContactInformation
    {
      get { return this.closestRelativeGuardianContactInformation; }
      set { this.closestRelativeGuardianContactInformation = value; }
    }

    public ValueListType SpecialClassification
    {
      get { return this.specialClassification; }
      set { this.specialClassification = value; }
    }

    public ClientEvacuationStatusDefaultType SpecialClassificationDefault
    {
      get { return this.specialClassificationDefault; }
      set { this.specialClassificationDefault = value; }
    }

    public SituationType Situation
    {
      get { return this.situation; }
      set { this.situation = value; }
    }

    public HealthCareProviderType HealthCareProvider
    {
      get { return this.healthCareProvider; }
      set { this.healthCareProvider = value; }
    }

    public ClientEncounterType ClientEncounter
    {
      get { return this.clientEncounter; }
      set { this.clientEncounter = value; }
    }

    #endregion // Public Accessors

    #region Public Member Functions
    
      public override void WriteXML(XmlWriter xwriter, string name) {
        this.Validate();
        
        xwriter.WriteStartDocument(false);
        xwriter.WriteStartElement(name);
        
        if (this.clientId != null)
        {
          foreach (ClientIDType val in this.clientId)
          {
            val.WriteXML(xwriter, "clientID");
          }
        }

        if (this.gender != null)
        {
          this.gender.WriteXML(xwriter, "gender");
        }

        if (this.clientAge != null)
        {
          this.clientAge.WriteXML(xwriter, "clientID");
        }

        if (this.raceEthnicity != null)
        {
          foreach (ValueListType val in this.raceEthnicity)
          {
            val.WriteXML(xwriter, "raceEthnicity");
          }
        }

        if (this.personalId != null)
        {
          xwriter.WriteStartElement("personalID");
          this.personalId.WriteXML(xwriter);
          xwriter.WriteEndElement();
        }

        if (this.hairColor != null)
        {
          this.hairColor.WriteXML(xwriter, "hairColor");
        }

        if (this.eyeColor != null)
        {
          this.eyeColor.WriteXML(xwriter, "eyeColor");
        }

        if (this.distinguishingMarks != null)
        {
          this.distinguishingMarks.WriteXML(xwriter, "distinguishingMarks");
        }

        if (this.primarySpokenLanguage != null)
        {
          this.primarySpokenLanguage.WriteXML(xwriter, "primarySpokenLanguage");
        }

        if (this.specialTransportationNeeds != null)
        {
          foreach (ValueListType val in this.specialTransportationNeeds)
          {
            val.WriteXML(xwriter, "specialTransportationNeeds");
          }
        }
        
        if (this.specialMedicalNeeds != null)
        {
          foreach (ValueListType val in this.specialMedicalNeeds)
          {
            val.WriteXML(xwriter, "specialMedicalNeeds");
          }
        }

        if (this.medicationAllergies != null)
        {
          foreach (ValueListType val in this.medicationAllergies)
          {
            val.WriteXML(xwriter, "medicationAllergies");
          }
        }

        if (this.currentMedication != null)
        {
          foreach (MedicationType val in this.currentMedication)
          {
            val.WriteXML(xwriter, "currentMedication");
          }
        }

        if (this.familyUnificationCode != null)
        {
          this.familyUnificationCode.WriteXML(xwriter, "familyUnificationCode");
        }

        if (this.barriersToPatientCare != null)
        {
          this.barriersToPatientCare.WriteXML(xwriter, "barriersToPatientCare");
        }

        if (this.evacuationDestinationRequired != null)
        {
          this.evacuationDestinationRequired.WriteXML(xwriter, "evacuationDestinationRequired");
        }

        if (this.evacuationDestinationRequiredDefault != null)
        {
          this.evacuationDestinationRequired.WriteXML(xwriter, "evacuationDestinationRequiredDefault");
        }

        if (this.clientContactInformation != null)
        {
          xwriter.WriteStartElement("clientContactInformation");
          this.clientContactInformation.WriteXML(xwriter);
          xwriter.WriteEndElement();
        }

        if (this.closestRelativeGuardianContactInformation != null)
        {
          foreach (PersonDetailsType val in this.closestRelativeGuardianContactInformation)
          {
            xwriter.WriteStartElement("closestRelativeGuardianContactInformation");
            val.WriteXML(xwriter);
            xwriter.WriteEndElement();
          }
        }

        if (this.specialClassification != null)
        {
          this.specialClassification.WriteXML(xwriter, "specialClassification");
        }

        if (this.specialClassificationDefault != null)
        {
          this.specialClassificationDefault.WriteXML(xwriter, "specialClassificationDefault");
        }

        if (this.situation != null)
        {
          this.situation.WriteXML(xwriter, "Situation");
        }

        if (this.healthCareProvider != null)
        {
          this.healthCareProvider.WriteXML(xwriter, "HealthCareProvider");
        }

        if (this.clientEncounter != null)
        {
          this.clientEncounter.WriteXML(xwriter, "ClientEncounter");
        }

        xwriter.WriteEndElement();
      }
    
      public override void ReadXML(XmlNode rootnode)
      {
        foreach (XmlNode node in rootnode)
        {
          if (String.IsNullOrEmpty(node.InnerText))
          {
            continue;
          }

          switch (node.LocalName)
          {
            case "clientID":
              if (this.clientId == null)
              {
                this.clientId = new List<ClientIDType>();
              }
              ClientIDType newval6 = new ClientIDType();
              this.clientId.Add(newval6);
              break;

            case "gender":
              if(this.gender == null)
              {
                this.gender = new GenderDefaultType();
              }
              this.gender.ReadXML(node);
              break;

            case "clientAge":
              if(this.clientAge == null)
              {
                this.clientAge = new ClientAgeType();
              }
              this.clientAge.ReadXML(node);
              break;

            case "raceEthnicity":
              if (this.raceEthnicity == null)
              {
                this.raceEthnicity = new List<ValueListType>();
              }
              ValueListType newval = new ValueListType();
              this.raceEthnicity.Add(newval);
              break;

            case "personalID":
              if(this.personalId == null)
              {
                this.personalId = new PersonDetailsType();
              }
              this.personalId.ReadXML(node);
              break;

            case "hairColor":
              if(this.hairColor == null)
              {
                this.hairColor = new ValueKeyType();
              }
              this.hairColor.ReadXML(node);
              break;

            case "eyeColor":
              if(this.eyeColor == null)
              {
                this.eyeColor = new ValueKeyType();
              }
              this.eyeColor.ReadXML(node);
              break;

            case "distinguishingMarks":
              if(this.distinguishingMarks == null)
              {
                this.distinguishingMarks = new EDXLStringTypeWrapper();
              }
              this.distinguishingMarks.ReadXML(node);
              break;

            case "primarySpokenLanguage":
              if(this.primarySpokenLanguage == null)
              {
                this.primarySpokenLanguage = new ValueKeyType();
              }
              this.primarySpokenLanguage.ReadXML(node);
              break;

            case "specialTransportationNeeds":
              if (this.specialTransportationNeeds == null)
              {
                this.specialTransportationNeeds = new List<ValueListType>();
              }
              ValueListType newval1 = new ValueListType();
              this.specialTransportationNeeds.Add(newval1);
              break;

            case "specialMedicalNeeds":
              if (this.specialMedicalNeeds == null)
              {
                this.specialMedicalNeeds = new List<ValueListType>();
              }
              ValueListType newval2 = new ValueListType();
              this.specialMedicalNeeds.Add(newval2);
              break;

            case "medicationAllergies":
              if (this.medicationAllergies == null)
              {
                this.medicationAllergies = new List<ValueListType>();
              }
              ValueListType newval3 = new ValueListType();
              this.medicationAllergies.Add(newval3);
              break;

            case "currentMedication":
              if (this.currentMedication == null)
              {
                this.currentMedication = new List<MedicationType>();
              }
              MedicationType newval4 = new MedicationType();
              this.currentMedication.Add(newval4);
              break;

            case "familyUnificationCode":
              if(this.familyUnificationCode == null)
              {
                this.familyUnificationCode = new EDXLStringTypeWrapper();
              }
              this.familyUnificationCode.ReadXML(node);
              break;

            case "barriersToPatientCare":
              if(this.barriersToPatientCare == null)
              {
                this.barriersToPatientCare = new ValueListType();
              }
              this.barriersToPatientCare.ReadXML(node);
              break;

            case "evacuationDestinationRequired":
              if(this.evacuationDestinationRequired == null)
              {
                this.evacuationDestinationRequired = new ValueKeyType();
              }
              this.evacuationDestinationRequired.ReadXML(node);
              break;

            case "evacuationDestinationRequiredDefault":
              if(this.evacuationDestinationRequiredDefault == null)
              {
                this.evacuationDestinationRequiredDefault = new ClientEvacuationStatusDefaultType();
              }
              this.evacuationDestinationRequiredDefault.ReadXML(node);
              break;

            case "clientContactInformation":
              if(this.clientContactInformation == null)
              {
                this.clientContactInformation = new PersonDetailsType();
              }
              this.clientContactInformation.ReadXML(node);
              break;

            case "closestRelativeGuardianContactInformation":
              if (this.closestRelativeGuardianContactInformation == null)
              {
                this.closestRelativeGuardianContactInformation = new List<PersonDetailsType>();
              }
              PersonDetailsType newval5 = new PersonDetailsType();
              this.closestRelativeGuardianContactInformation.Add(newval5);
              break;

            case "specialClassification":
              if(this.specialClassification == null)
              {
                this.specialClassification = new ValueListType();
              }
              this.specialClassification.ReadXML(node);
              break;

            case "specialClassificationDefault":
              if(this.specialClassificationDefault == null)
              {
                this.specialClassificationDefault = new ClientEvacuationStatusDefaultType();
              }
              this.specialClassificationDefault.ReadXML(node);
              break;

            case "Situation":
              if(this.Situation == null)
              {
                this.Situation = new SituationType();
              }
              this.Situation.ReadXML(node);
              break;

            case "HealthCareProvider":
              if(this.HealthCareProvider == null)
              {
                this.HealthCareProvider = new HealthCareProviderType();
              }
              this.HealthCareProvider.ReadXML(node);
              break;

            case "ClientEncounter":
              if(this.ClientEncounter == null)
              {
                this.ClientEncounter = new ClientEncounterType();
              }
              this.ClientEncounter.ReadXML(node);
              break;

          }
        }

        this.Validate();
      }
    
    #endregion // Public Member Functions

    #region Private Member Functions
    
      protected override void Validate()
      {
        if (clientId.Count < 1)
        {
          throw new ArgumentException("There must be at least one clientId element");
        }

        if (this.gender == null)
        {
          throw new ArgumentNullException("A gender element is required. No null values.");
        }

        if (this.clientAge == null)
        {
          throw new ArgumentNullException("A clientAge element is required. No null values.");
        }

        if (this.evacuationDestinationRequired != null && this.evacuationDestinationRequiredDefault != null)
        {
          throw new ArgumentException("One of evacuationDestinationRequired or evacuationDestinationRequiredDefault can be used, not both.");
        }

        if (this.specialClassification != null && this.specialClassificationDefault != null)
        {
          throw new ArgumentException("One of specialClassification or specialClassificationDefault can be used, not both.");
        }

        if (this.situation == null)
        {
          throw new ArgumentNullException("A situation element is required. No null values.");
        }

        if (this.healthCareProvider == null)
        {
          throw new ArgumentNullException("A healthCareProvider element is required. No null values.");
        }

        if (this.clientEncounter == null)
        {
          throw new ArgumentNullException("A clientEncounter element is required. No null values.");
        }
      }
      
    #endregion // Private Member Functions

  }
}
